package com.mashibing.juc.c_026_00_interview.A1B2C3;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

class FIFOMutex {

    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public void lock() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);

        // 当前线程不是等待队列队首线程 或 比较并设置原子锁值失败 则锁定(阻塞)当前线程
        while (waiters.peek() != current || !locked.compareAndSet(false, true)) {
            System.out.printf("\033[34m %s ===>> 被锁定 \033[0m\n",
                    Thread.currentThread().getName());
            LockSupport.park(this);
            if (Thread.interrupted()) wasInterrupted = true;

        }
        System.out.printf("\033[33m %s ===>> 获取锁并移除等待队列 \033[0m\n",
                Thread.currentThread().getName());
        waiters.remove();
        if (wasInterrupted) current.interrupt();
    }

    public void unlock() {
        locked.set(false);
        LockSupport.unpark(waiters.peek());
        System.out.printf("\033[34m %s ===>> unlock() \033[0m\n",
                Thread.currentThread().getName());
    }

}
